/*******************************************************************************
 * This file is part of the EEG-database project
 * 
 *   ==========================================
 *  
 *   Copyright (C) 2013 by University of West Bohemia (http://www.zcu.cz/en/)
 *  
 *  ***********************************************************************************************************************
 *  
 *   Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 *   the License. You may obtain a copy of the License at
 *  
 *       http://www.apache.org/licenses/LICENSE-2.0
 *  
 *   Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 *   an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 *   specific language governing permissions and limitations under the License.
 *  
 *  ***********************************************************************************************************************
 *  
 *   Person.java, 2013/10/02 00:01 Jakub Rinkes
 ******************************************************************************/
package cz.zcu.kiv.eegdatabase.data.pojo;

import cz.zcu.kiv.eegdatabase.wui.ui.experiments.converters.IAutoCompletable;
import cz.zcu.kiv.formgen.annotation.*;
import org.hibernate.annotations.GenericGenerator;
import thewebsemantic.annotations.Ignore;

import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;

// Generated 2.12.2013 0:56:28 by Hibernate Tools 3.4.0.CR1

/**
 * Person generated by hbm2java
 */
@Form
@Entity
@Table(name = "PERSON")
public class Person implements Serializable, Comparable<Person>, IAutoCompletable {

	@FormId
	private int personId;
	@FormItem
	private String facebookId;
	@FormItem(required = true)
	private String email;
	@FormItem(preview = PreviewLevel.MINOR)
	private String givenname;
	@FormItem(required = true, preview = PreviewLevel.MAJOR)
	private String surname;
	@FormItem(required = true)
	private Timestamp dateOfBirth;
	@FormItem(required = true)
	@FormItemRestriction(values = {"M", "F"})
	private char gender;
	@FormItem(required = true)
	@FormItemRestriction(values = {"L", "R", "X"})
	private char laterality;
	@FormItem
	private String phoneNumber;
	@FormItem
	private String note;
	private String username;
	private String password;
	private String authority;
    private String title;
    private String address;
    private String city;
    private String state;
    private String zipCode;
    private String url;
    private String phone;
	private Timestamp registrationDate;
	private boolean confirmed;
	private boolean lock = false;
	private String authenticationHash;
	//@FormItem    // contains reference to Person - cycle
	private ResearchGroup defaultGroup;
	@FormItem
	private EducationLevel educationLevel;

    private String organizationType;
    private String organization;
    private String jobTitle;
    private String orgAddress;
    private String orgCity;
    private String orgState;
    private String orgZipCode;
    private String orgUrl;
    private String orgPhone;
    private String VAT;
    private String country;
    private String orgCountry;

	private Set<Experiment> experiments = new HashSet<Experiment>(0);
	private Set<ResearchGroupMembership> researchGroupMemberships = new HashSet<ResearchGroupMembership>(
					0);
	private Set<Scenario> scenarios = new HashSet<Scenario>(0);
	private Set<Experiment> experimentsForOwnerId = new HashSet<Experiment>(0);
	private Set<Experiment> experimentsForSubjectPersonId = new HashSet<Experiment>(
					0);
	private Set<History> histories = new HashSet<History>(0);
	private Set<PersonOptParamVal> personOptParamVals = new HashSet<PersonOptParamVal>(
					0);
	private Set<ResearchGroup> researchGroups = new HashSet<ResearchGroup>(0);
	private Set<GroupPermissionRequest> requests = new HashSet<GroupPermissionRequest>(
					0);
	private Set<Article> articlesSubscribtions = new HashSet<Article>(0);
	private Set<ResearchGroup> articlesGroupSubscribtions = new HashSet<ResearchGroup>(
					0);
	private Set<ServiceResult> results = new HashSet<ServiceResult>(0);
	private Set<PersonalLicense> personalLicenses = new HashSet<PersonalLicense>(0);
    private Set<PersonMembershipPlan> personMembershipPlans = new HashSet<PersonMembershipPlan>(0);

	public Person() {
	}

	public Person(String surname, char gender, char laterality) {
		this.surname = surname;
		this.gender = gender;
		this.laterality = laterality;
	}

	public Person(String facebookId, String email, String givenname,
					String surname, Timestamp dateOfBirth, char gender,
					char laterality, String phoneNumber, String note, String username,
					String password, String authority, Timestamp registrationDate,
					boolean confirmed, String authenticationHash,
					ResearchGroup defaultGroup, EducationLevel educationLevel,
					Set<Experiment> experiments,
					Set<ResearchGroupMembership> researchGroupMemberships,
					Set<Scenario> scenarios, Set<Experiment> experimentsForOwnerId,
					Set<Experiment> experimentsForSubjectPersonId,
					Set<History> histories, Set<PersonOptParamVal> personOptParamVals,
					Set<ResearchGroup> researchGroups,
					Set<GroupPermissionRequest> requests,
					Set<Article> articlesSubscribtions,
					Set<ResearchGroup> articlesGroupSubscribtions,
					Set<ServiceResult> results) {
		this.facebookId = facebookId;
		this.email = email;
		this.givenname = givenname;
		this.surname = surname;
		this.dateOfBirth = dateOfBirth;
		this.gender = gender;
		this.laterality = laterality;
		this.phoneNumber = phoneNumber;
		this.note = note;
		this.username = username;
		this.password = password;
		this.authority = authority;
		this.registrationDate = registrationDate;
		this.confirmed = confirmed;
		this.authenticationHash = authenticationHash;
		this.defaultGroup = defaultGroup;
		this.educationLevel = educationLevel;
		this.experiments = experiments;
		this.researchGroupMemberships = researchGroupMemberships;
		this.scenarios = scenarios;
		this.experimentsForOwnerId = experimentsForOwnerId;
		this.experimentsForSubjectPersonId = experimentsForSubjectPersonId;
		this.histories = histories;
		this.personOptParamVals = personOptParamVals;
		this.researchGroups = researchGroups;
		this.requests = requests;
		this.articlesSubscribtions = articlesSubscribtions;
		this.articlesGroupSubscribtions = articlesGroupSubscribtions;
		this.results = results;
	}

	@GenericGenerator(name = "generator", strategy = "increment")
	@Id
	@GeneratedValue(generator = "generator")
	@Column(name = "PERSON_ID", nullable = false, precision = 22, scale = 0)
	public int getPersonId() {
		return this.personId;
	}

	public void setPersonId(int personId) {
		this.personId = personId;
	}

	@Column(name = "FB_UID", unique = true, length = 30)
	public String getFacebookId() {
		return this.facebookId;
	}

	public void setFacebookId(String facebookId) {
		this.facebookId = facebookId;
	}

	@Deprecated
	@Column(name = "EMAIL", unique = true)
	public String getEmail() {
		return this.email;
	}
	
	@Deprecated
	public void setEmail(String email) {
		this.email = email;
	}

	@Column(name = "GIVENNAME", length = 50)
	public String getGivenname() {
		return this.givenname;
	}

	public void setGivenname(String givenname) {
		this.givenname = givenname;
	}

	@Column(name = "SURNAME", nullable = false, length = 50)
	public String getSurname() {
		return this.surname;
	}

	public void setSurname(String surname) {
		this.surname = surname;
	}

	@Column(name = "DATE_OF_BIRTH", length = 7, nullable = true)
	public Timestamp getDateOfBirth() {
		return this.dateOfBirth;
	}

	public void setDateOfBirth(Timestamp dateOfBirth) {
		this.dateOfBirth = dateOfBirth;
	}

	@Column(name = "GENDER", nullable = false, length = 1)
	public char getGender() {
		return this.gender;
	}

	public void setGender(char gender) {
		this.gender = gender;
	}

	@Column(name = "LATERALITY", nullable = false, length = 1)
	public char getLaterality() {
		return this.laterality;
	}

	public void setLaterality(char laterality) {
		this.laterality = laterality;
	}

	@Column(name = "PHONE_NUMBER", length = 20)
	public String getPhoneNumber() {
		return this.phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	@Column(name = "NOTE")
	public String getNote() {
		return this.note;
	}

	public void setNote(String note) {
		this.note = note;
	}

	@Column(name = "USERNAME", unique = true, nullable = false, length = 50)
	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	@Column(name = "PASSWORD", length = 80)
	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(name = "AUTHORITY", length = 50, nullable = false)
	public String getAuthority() {
		return this.authority;
	}

	public void setAuthority(String authority) {
		this.authority = authority;
	}

	@Column(name = "REGISTRATION_DATE", length = 7)
	public Timestamp getRegistrationDate() {
		return this.registrationDate;
	}

	public void setRegistrationDate(Timestamp registrationDate) {
		this.registrationDate = registrationDate;
	}

    @Column(name = "TITLE")
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Column(name = "ADDRESS")
    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Column(name = "CITY")
    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Column(name = "STATE")
    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @Column(name = "ZIP_CODE")
    public String getZipCode() {
        return zipCode;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    @Column(name = "URL")
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    @Column(name = "PHONE")
    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Column(name = "ORGANIZATION_TYPE")
    public String getOrganizationType() {
        return organizationType;
    }

    public void setOrganizationType(String organizationType) {
        this.organizationType = organizationType;
    }

    @Column(name = "ORGANIZATION")
    public String getOrganization() {
        return organization;
    }

    public void setOrganization(String organization) {
        this.organization = organization;
    }

    @Column(name = "JOB_TITLE")
    public String getJobTitle() {
        return jobTitle;
    }

    public void setJobTitle(String jobTitle) {
        this.jobTitle = jobTitle;
    }

    @Column(name = "ORG_ADDRESS")
    public String getOrgAddress() {
        return orgAddress;
    }

    public void setOrgAddress(String orgAddress) {
        this.orgAddress = orgAddress;
    }

    @Column(name = "ORG_CITY")
    public String getOrgCity() {
        return orgCity;
    }

    public void setOrgCity(String orgCity) {
        this.orgCity = orgCity;
    }

    @Column(name = "ORG_STATE")
    public String getOrgState() {
        return orgState;
    }

    public void setOrgState(String orgState) {
        this.orgState = orgState;
    }

    @Column(name = "ORG_ZIP_CODE")
    public String getOrgZipCode() {
        return orgZipCode;
    }

    public void setOrgZipCode(String orgZipCode) {
        this.orgZipCode = orgZipCode;
    }

    @Column(name = "ORG_URL")
    public String getOrgUrl() {
        return orgUrl;
    }

    public void setOrgUrl(String orgUrl) {
        this.orgUrl = orgUrl;
    }

    @Column(name = "ORG_PHONE")
    public String getOrgPhone() {
        return orgPhone;
    }

    public void setOrgPhone(String orgPhone) {
        this.orgPhone = orgPhone;
    }

    @Column(name = "VAT")
    public String getVAT() {
        return VAT;
    }

    public void setVAT(String VAT) {
        this.VAT = VAT;
    }

    @Column(name = "COUNTRY")
    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Column(name = "ORG_COUNTRY")
    public String getOrgCountry() {
        return orgCountry;
    }

    public void setOrgCountry(String orgCountry) {
        this.orgCountry = orgCountry;
    }

    @Column(name = "CONFIRMED")
	public boolean isConfirmed() {
		return this.confirmed;
	}

	public void setConfirmed(boolean confirmed) {
		this.confirmed = confirmed;
	}

	@Column(name = "AUTHENTICATION", length = 50)
	public String getAuthenticationHash() {
		return this.authenticationHash;
	}

	public void setAuthenticationHash(String authenticationHash) {
		this.authenticationHash = authenticationHash;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "DEFAULT_GROUP_ID")
	public ResearchGroup getDefaultGroup() {
		return this.defaultGroup;
	}

	public void setDefaultGroup(ResearchGroup defaultGroup) {
		this.defaultGroup = defaultGroup;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "EDUCATION_LEVEL_ID")
	public EducationLevel getEducationLevel() {
		return this.educationLevel;
	}

	public void setEducationLevel(EducationLevel educationLevel) {
		this.educationLevel = educationLevel;
	}

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "COEXPERIMENTER_REL", joinColumns = {
		@JoinColumn(name = "PERSON_ID", nullable = false, updatable = false)}, inverseJoinColumns = {
		@JoinColumn(name = "EXPERIMENT_ID", nullable = false, updatable = false)})
	public Set<Experiment> getExperiments() {
		return this.experiments;
	}

	public void setExperiments(Set<Experiment> experiments) {
		this.experiments = experiments;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
	public Set<ResearchGroupMembership> getResearchGroupMemberships() {
		return this.researchGroupMemberships;
	}

	public void setResearchGroupMemberships(
					Set<ResearchGroupMembership> researchGroupMemberships) {
		this.researchGroupMemberships = researchGroupMemberships;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
	public Set<Scenario> getScenarios() {
		return this.scenarios;
	}

	public void setScenarios(Set<Scenario> scenarios) {
		this.scenarios = scenarios;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "personByOwnerId")
	public Set<Experiment> getExperimentsForOwnerId() {
		return this.experimentsForOwnerId;
	}

	public void setExperimentsForOwnerId(Set<Experiment> experimentsForOwnerId) {
		this.experimentsForOwnerId = experimentsForOwnerId;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "personBySubjectPersonId")
	public Set<Experiment> getExperimentsForSubjectPersonId() {
		return this.experimentsForSubjectPersonId;
	}

	public void setExperimentsForSubjectPersonId(
					Set<Experiment> experimentsForSubjectPersonId) {
		this.experimentsForSubjectPersonId = experimentsForSubjectPersonId;
	}

	@Ignore
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
	public Set<History> getHistories() {
		return this.histories;
	}

	public void setHistories(Set<History> histories) {
		this.histories = histories;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
	public Set<PersonOptParamVal> getPersonOptParamVals() {
		return this.personOptParamVals;
	}

	public void setPersonOptParamVals(Set<PersonOptParamVal> personOptParamVals) {
		this.personOptParamVals = personOptParamVals;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
	public Set<ResearchGroup> getResearchGroups() {
		return this.researchGroups;
	}

	public void setResearchGroups(Set<ResearchGroup> researchGroups) {
		this.researchGroups = researchGroups;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
	public Set<GroupPermissionRequest> getRequests() {
		return this.requests;
	}

	public void setRequests(Set<GroupPermissionRequest> requests) {
		this.requests = requests;
	}

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "ARTICLES_SUBSCRIBTIONS", joinColumns = {
		@JoinColumn(name = "PERSON_ID", nullable = false, updatable = false)}, inverseJoinColumns = {
		@JoinColumn(name = "ARTICLE_ID", nullable = false, updatable = false)})
	public Set<Article> getArticlesSubscribtions() {
		return this.articlesSubscribtions;
	}

	public void setArticlesSubscribtions(Set<Article> articlesSubscribtions) {
		this.articlesSubscribtions = articlesSubscribtions;
	}

	@ManyToMany(fetch = FetchType.LAZY)
	@JoinTable(name = "ARTICLES_GROUP_SUBSCRIBTIONS", joinColumns = {
		@JoinColumn(name = "PERSON_ID", nullable = false, updatable = false)}, inverseJoinColumns = {
		@JoinColumn(name = "RESEARCH_GROUP_ID", nullable = false, updatable = false)})
	public Set<ResearchGroup> getArticlesGroupSubscribtions() {
		return this.articlesGroupSubscribtions;
	}

	public void setArticlesGroupSubscribtions(
					Set<ResearchGroup> articlesGroupSubscribtions) {
		this.articlesGroupSubscribtions = articlesGroupSubscribtions;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "owner")
	public Set<ServiceResult> getResults() {
		return this.results;
	}

	public void setResults(Set<ServiceResult> results) {
		this.results = results;
	}

	@OneToMany(mappedBy = "person")
	public Set<PersonalLicense> getPersonalLicenses() {
		return personalLicenses;
	}

	public void setPersonalLicenses(Set<PersonalLicense> personalLicenses) {
		this.personalLicenses = personalLicenses;
	}

    @OneToMany(mappedBy = "person")
    public Set<PersonMembershipPlan> getPersonMembershipPlans() {
        return personMembershipPlans;
    }

    public void setPersonMembershipPlans(Set<PersonMembershipPlan> personMembershipPlans) {
        this.personMembershipPlans = personMembershipPlans;
    }

    @Column(name="LOCK" ,nullable=false, columnDefinition = "BOOLEAN DEFAULT FALSE")
    public boolean isLock() {
        return lock;
    }

    public void setLock(boolean lock) {
        this.lock = lock;
    }

    @Transient
	public String getFullName() {

		if (getGivenname() == null && getSurname() == null) {
			return null;
		}

		String fullName = (getSurname() != null) ? getSurname() : "";
		fullName += (getGivenname() != null) ? " " + getGivenname() : "";
		return fullName;
	}

	@Override
	public int compareTo(Person person) {
		return this.surname.compareTo(person.getSurname());
	}

	@Transient
	@Override
	public String getAutoCompleteData() {

		if (getGivenname() == null && getSurname() == null && getEmail() == null) {
			return null;
		}

		String fullName = (getSurname() != null) ? getSurname() : "";
		fullName += (getGivenname() != null) ? " " + getGivenname() : "";
		fullName += (getUsername() != null) ? " " + getUsername() : "";
		return fullName;
	}
	
	@Override
	public boolean equals(Object obj) {
	    
	    if (obj == null) {
	        return false;
	    }
	    
	    if(!obj.getClass().equals(this.getClass())) {
	        return false;
	    }
	    
	    Person other = (Person) obj;
	    
	    return getPersonId() == other.getPersonId();
	}
	
	@Override
	public int hashCode() {
	    return getPersonId();
	}
}
